﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using System.Runtime.Serialization.Formatters.Binary;

namespace cubeworld
{
    class Data
    {
        public static SamplerState st = new SamplerState();

        public static Random random = new Random();
        public static SpriteBatch spriteBatch;
        public static GraphicsDeviceManager graphics;
        public static ContentManager content;
        public static CubeModel cubeModel;
        public static World world;
        public static FPSCounter fpsCounter;
        public static Entity.PlayerEntity player;

        public static SpriteFont debugFont;
        public static Texture2D kreuz;
        public static Texture2D logo;
        public static Texture2D buttonNormal;
        public static Texture2D buttonHover;
        public static Texture2D bg50;
        public static Texture2D knob, bar;
        public static Texture2D check, box;
        public static Effect instancedEffect;

        public static Camera camera;
        public static int renderDistance = 30;

        public static Screen currentScreen = new ScreenManager.TitleScreen();
        public static Screen overlayScreen = null;

        public static Vector2 kreuzPos;

        public static void SetUp(SpriteBatch sb, ContentManager ct, GraphicsDeviceManager gc)
        {
            camera = new Camera(new Vector3(0, 0, 5), Vector3.Zero, 1000.0f);
            camera.SetUpMovement(true, true, 0.05f, 0.005f);
            player = new Entity.PlayerEntity("Test");
            st.Filter = TextureFilter.Point;
            content = ct;
            spriteBatch = sb;
            graphics = gc;
            fpsCounter = new FPSCounter();

            cubeModel = new CubeModel();

            instancedEffect = content.Load<Effect>("effects\\InstancedModel");
            instancedEffect.CurrentTechnique = instancedEffect.Techniques["HardwareInstancing"];
            instancedEffect.Parameters["TextureAtlas"].SetValue(content.Load<Texture2D>("BlockTextures\\texture_atlas"));
            debugFont = content.Load<SpriteFont>("fonts\\debug");
            kreuz = content.Load<Texture2D>("GUI\\kreuz");
            logo = content.Load<Texture2D>("GUI\\cubeworlds_logo");
            buttonNormal = content.Load<Texture2D>("GUI\\buttonNormal");
            buttonHover = content.Load<Texture2D>("GUI\\buttonHover");
            bg50 = content.Load<Texture2D>("GUI\\50bg");
            knob = Data.content.Load<Texture2D>("GUI\\knob");
            bar = Data.content.Load<Texture2D>("GUI\\bar");
            check = Data.content.Load<Texture2D>("GUI\\check");
            box = Data.content.Load<Texture2D>("GUI\\box");
            kreuzPos = new Vector2(graphics.PreferredBackBufferWidth * 0.5f - 10, graphics.PreferredBackBufferHeight * 0.5f - 10);

            currentScreen.Init();

            // JUST FOR TESTING PURPOSES!
            /*
            #region
            string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\save.world";
            if (System.IO.File.Exists(path))
            {
                System.IO.Stream stream = System.IO.File.Open(path, System.IO.FileMode.Open);

                System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                world = (World)formatter.Deserialize(stream);

                stream.Close();
            }
            #endregion
            */
        }

        public static void Update(float elapsedTime)
        {
            if (overlayScreen != null)
            {
                overlayScreen.Update(elapsedTime);
            }
            else
            {
                currentScreen.Update(elapsedTime);
            }
        }

        public static void Draw(float elapsedTime)
        {
            Data.spriteBatch.Begin(SpriteSortMode.Deferred , BlendState.NonPremultiplied, Data.st, DepthStencilState.None, RasterizerState.CullNone);
            currentScreen.Render(elapsedTime);
            if (overlayScreen != null) { overlayScreen.Render(elapsedTime); }
            spriteBatch.End();
        }

        public static void DrawWorld(float elapsedTime)
        {
            fpsCounter.Draw(elapsedTime);

            MainGame.Device.DepthStencilState = DepthStencilState.Default;
            MainGame.Device.SamplerStates[0] = st;
            world.Draw();

            spriteBatch.Draw(kreuz, kreuzPos, Color.White);
            spriteBatch.DrawString(debugFont, "Blocks: " + Convert.ToString(world.blocks.Count) + " X: " + Data.camera.position.X + " Y: " + Data.camera.position.Y + " Z: " + Data.camera.position.Z, new Vector2(10, 10), Color.Black);
            spriteBatch.DrawString(debugFont, "FPS: " + fpsCounter.FPS + " | UPS: " + fpsCounter.UPS, new Vector2(10, 30), Color.Black);
            spriteBatch.DrawString(debugFont, "Selected Block: " + world.currentSelectedBlock.ToString(), new Vector2(10, 50), Color.Black);

        }

        public static void SetScreen(Screen screen)
        {
            currentScreen = screen;
            currentScreen.Init();
        }

        public static void SetOverlayScreen(Screen screen)
        {
            overlayScreen = screen;
            overlayScreen.Init();
        }

        public static void CloseOverlayScreen()
        {
            overlayScreen = null;
        }

        public static void changeMouse(bool visible)
        {
            MainGame.mouseVisible = visible;
        }

        public static void save()
        {
            string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\save.world";
            System.IO.Stream streamToSerealize = System.IO.File.Create(path);

            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(streamToSerealize, Data.world);

            streamToSerealize.Flush();
            streamToSerealize.Close();
        }
    }
}
